{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "https://zhuanlan.zhihu.com/p/918102867\n",
    "\n",
    "本文沿着你给出的脉络继续展开，重点放在**如何用 CRTP 取代传统动态多态实现经典设计模式**，并补充 C++23 中新增的语法（例如显式对象形参）对静态多态写法的影响。随后我们再看 Mixin 的现代玩法，以及二者的组合。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 为什么要关注 CRTP 与 Mixin？"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- **CRTP（Curiously Recurring Template Pattern）**：一种静态多态实现方式，可替代传统虚函数，减少运行时开销。\n",
    "- **Mixin（混入）**：通过多重继承与模板组合，把行为模块化，提升代码复用能力。\n",
    "- C++23 起对 CRTP 提供了「显式对象形参」语法支持，使其编写更简洁。\n",
    "- 将 CRTP 与 Mixin 结合，可构建高效、灵活的静态多态框架，适合工程实践中的设计模式实现。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# CRTP 基础"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- 静态多态 vs 动态多态\n",
    "\n",
    "| 对比项              | 动态多态（虚函数） | 静态多态（CRTP）           |\n",
    "| ------------------- | ------------------ | -------------------------- |\n",
    "| 调用绑定时间        | 运行时             | 编译期                     |\n",
    "| 性能                | 需虚表查找，略慢   | 直接展开，无虚表开销       |\n",
    "| 可扩展性            | 新类型需继承虚基类 | 新类型模板实参化即可       |\n",
    "| 语法复杂度（C++23） | 熟悉易用           | 逐步简化（显式对象形参等） |"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- 虚函数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "cpp"
    }
   },
   "outputs": [],
   "source": [
    "#include <iostream>\n",
    "#include <memory>\n",
    "\n",
    "class VirtualBase {\n",
    "public:\n",
    "    virtual ~VirtualBase() = default;\n",
    "    virtual void test() = 0;\n",
    "};\n",
    "\n",
    "class VirtualDerived1 : public VirtualBase {\n",
    "public:\n",
    "    void test() override {\n",
    "        std::cout << \"VirtualDerived1\\n\";\n",
    "    }\n",
    "};\n",
    "\n",
    "int main() {\n",
    "    std::unique_ptr<VirtualBase> obj = std::make_unique<VirtualDerived1>();\n",
    "    obj->test(); // 打印：VirtualDerived1\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- 传统 CRTP 写法"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "cpp"
    }
   },
   "outputs": [],
   "source": [
    "#include <iostream>\n",
    "\n",
    "// 基类模板\n",
    "template <typename Derived>\n",
    "class CrtpBase {\n",
    "public:\n",
    "    void test() {\n",
    "        static_cast<Derived&>(*this).impl();\n",
    "    }\n",
    "};\n",
    "\n",
    "// 派生类\n",
    "class CrtpDerived1 : public CrtpBase<CrtpDerived1> {\n",
    "public:\n",
    "    void impl() {\n",
    "        std::cout << \"CrtpDerived1\\n\";\n",
    "    }\n",
    "};\n",
    "\n",
    "int main() {\n",
    "    CrtpDerived1 obj;\n",
    "    obj.test(); // 打印：CrtpDerived1\n",
    "\n",
    "    CrtpBase<CrtpDerived1>& as_base = obj;\n",
    "    as_base.test(); // 同样打印：CrtpDerived1\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- C++23 新写法（显式对象形参）\n",
    "  - **核心机制**：基类模板在实例化时将 `this` 指针转换为具体派生类类型，实现“静态分派”。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "cpp"
    }
   },
   "outputs": [],
   "source": [
    "#include <iostream>\n",
    "\n",
    "class CrtpBase23 {\n",
    "public:\n",
    "    void test(this auto&& self) {\n",
    "        self.impl();\n",
    "    }\n",
    "};\n",
    "\n",
    "class CrtpDerived1_23 : public CrtpBase23 {\n",
    "public:\n",
    "    void impl() {\n",
    "        std::cout << \"CrtpDerived1 (C++23)\\n\";\n",
    "    }\n",
    "};\n",
    "\n",
    "int main() {\n",
    "    CrtpDerived1_23 obj;\n",
    "    obj.test(); // 打印：CrtpDerived1 (C++23)\n",
    "\n",
    "    CrtpBase23& as_base = obj;\n",
    "    as_base.test(); // 同样打印：CrtpDerived1 (C++23)\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# CRTP 在设计模式中的应用"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "在设计模式中的应用\n",
    "- **传统写法**：基于虚函数 + `if-else` 分支，维护成本高。\n",
    "- **CRTP 写法**：利用模板参数实例化产品类型，不再硬编码产品列表。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "cpp"
    }
   },
   "outputs": [],
   "source": [
    "// 传统写法\n",
    "\n",
    "#include <iostream>\n",
    "#include <memory>\n",
    "#include <string>\n",
    "\n",
    "class Cars {\n",
    "public:\n",
    "    virtual ~Cars() = default;\n",
    "    virtual void run() = 0;\n",
    "};\n",
    "\n",
    "class Truck : public Cars {\n",
    "public:\n",
    "    void run() override {\n",
    "        std::cout << \"Truck Run.\\n\";\n",
    "    }\n",
    "};\n",
    "\n",
    "class Motor : public Cars {\n",
    "public:\n",
    "    void run() override {\n",
    "        std::cout << \"Motor Run.\\n\";\n",
    "    }\n",
    "};\n",
    "\n",
    "class CarsFactory {\n",
    "public:\n",
    "    std::unique_ptr<Cars> productCar(const std::string& car_type) {\n",
    "        if (car_type == \"Truck\") {\n",
    "            return std::make_unique<Truck>();\n",
    "        } else if (car_type == \"Motor\") {\n",
    "            return std::make_unique<Motor>();\n",
    "        }\n",
    "        return nullptr;\n",
    "    }\n",
    "};\n",
    "\n",
    "int main() {\n",
    "    CarsFactory factory;\n",
    "\n",
    "    if (auto truck = factory.productCar(\"Truck\")) {\n",
    "        truck->run(); // 打印：Truck Run.\n",
    "    }\n",
    "\n",
    "    if (auto motor = factory.productCar(\"Motor\")) {\n",
    "        motor->run(); // 打印：Motor Run.\n",
    "    }\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "cpp"
    }
   },
   "outputs": [],
   "source": [
    "#include <iostream>\n",
    "#include <memory>\n",
    "\n",
    "template <typename Derived>\n",
    "class Cars {\n",
    "public:\n",
    "    void run() {\n",
    "        static_cast<Derived*>(this)->runImpl();\n",
    "    }\n",
    "};\n",
    "\n",
    "class Truck : public Cars<Truck> {\n",
    "public:\n",
    "    void runImpl() {\n",
    "        std::cout << \"Truck Run.\\n\";\n",
    "    }\n",
    "};\n",
    "\n",
    "class Motor : public Cars<Motor> {\n",
    "public:\n",
    "    void runImpl() {\n",
    "        std::cout << \"Motor Run.\\n\";\n",
    "    }\n",
    "};\n",
    "\n",
    "class CarsFactory {\n",
    "public:\n",
    "    template <typename Derived>\n",
    "    std::unique_ptr<Derived> productCar() {\n",
    "        return std::make_unique<Derived>();\n",
    "    }\n",
    "};\n",
    "\n",
    "int main() {\n",
    "    CarsFactory factory;\n",
    "\n",
    "    auto truck = factory.productCar<Truck>();\n",
    "    truck->run(); // 打印：Truck Run.\n",
    "\n",
    "    auto motor = factory.productCar<Motor>();\n",
    "    motor->run(); // 打印：Motor Run.\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "建造者模式\n",
    "\n",
    "- **传统写法**：依赖虚函数实现不同建造步骤。\n",
    "- **CRTP 写法**：通过模板实现静态多态，指挥者可接受任意建造者实例，减少虚调用开销。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "cpp"
    }
   },
   "outputs": [],
   "source": [
    "// 传统虚函数写法（动态多态）\n",
    "\n",
    "#include <iostream>\n",
    "#include <string>\n",
    "#include <memory>\n",
    "\n",
    "// 产品：Car（由轮子和发动机组成）\n",
    "class Car {\n",
    "public:\n",
    "    void setWheels(const std::string& wheels) {\n",
    "        wheels_ = wheels;\n",
    "        std::cout << wheels_ << '\\n';\n",
    "    }\n",
    "\n",
    "    void setEngine(const std::string& engine) {\n",
    "        engine_ = engine;\n",
    "        std::cout << engine_ << '\\n';\n",
    "    }\n",
    "\n",
    "private:\n",
    "    std::string wheels_;\n",
    "    std::string engine_;\n",
    "};\n",
    "\n",
    "// 抽象建造者：通过虚函数实现多态\n",
    "class Builder {\n",
    "public:\n",
    "    virtual ~Builder() = default;\n",
    "\n",
    "    virtual void buildWheels() = 0;\n",
    "    virtual void buildEngine() = 0;\n",
    "\n",
    "    Car release() {\n",
    "        return std::move(car_);\n",
    "    }\n",
    "\n",
    "protected:\n",
    "    Car car_;\n",
    "};\n",
    "\n",
    "// 具体建造者：卡车\n",
    "class TruckBuilder : public Builder {\n",
    "public:\n",
    "    void buildWheels() override {\n",
    "        car_.setWheels(\"Truck Wheels.\");\n",
    "    }\n",
    "\n",
    "    void buildEngine() override {\n",
    "        car_.setEngine(\"Truck Engine.\");\n",
    "    }\n",
    "};\n",
    "\n",
    "// 具体建造者：摩托车\n",
    "class MotorBuilder : public Builder {\n",
    "public:\n",
    "    void buildWheels() override {\n",
    "        car_.setWheels(\"Motor Wheels.\");\n",
    "    }\n",
    "\n",
    "    void buildEngine() override {\n",
    "        car_.setEngine(\"Motor Engine.\");\n",
    "    }\n",
    "};\n",
    "\n",
    "// 指挥者：按步骤调用建造者\n",
    "class Director {\n",
    "public:\n",
    "    Car buildCar(Builder& builder) {\n",
    "        builder.buildWheels();\n",
    "        builder.buildEngine();\n",
    "        return builder.release();\n",
    "    }\n",
    "};\n",
    "\n",
    "int main() {\n",
    "    Director director;\n",
    "\n",
    "    TruckBuilder truckBuilder;\n",
    "    Car truck = director.buildCar(truckBuilder);\n",
    "    (void)truck;\n",
    "\n",
    "    MotorBuilder motorBuilder;\n",
    "    Car motor = director.buildCar(motorBuilder);\n",
    "    (void)motor;\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "cpp"
    }
   },
   "outputs": [],
   "source": [
    "#include <iostream>\n",
    "#include <string>\n",
    "#include <utility>\n",
    "\n",
    "// 产品：Car\n",
    "class Car {\n",
    "public:\n",
    "    void setWheels(const std::string& wheels) {\n",
    "        wheels_ = wheels;\n",
    "        std::cout << wheels_ << '\\n';\n",
    "    }\n",
    "\n",
    "    void setEngine(const std::string& engine) {\n",
    "        engine_ = engine;\n",
    "        std::cout << engine_ << '\\n';\n",
    "    }\n",
    "\n",
    "private:\n",
    "    std::string wheels_;\n",
    "    std::string engine_;\n",
    "};\n",
    "\n",
    "// CRTP 基类：统一接口 + 静态分派\n",
    "template <typename Derived>\n",
    "class Builder {\n",
    "public:\n",
    "    void buildWheels() {\n",
    "        static_cast<Derived&>(*this).buildWheelsImpl();\n",
    "    }\n",
    "\n",
    "    void buildEngine() {\n",
    "        static_cast<Derived&>(*this).buildEngineImpl();\n",
    "    }\n",
    "\n",
    "    Car release() {\n",
    "        return std::move(car_);\n",
    "    }\n",
    "\n",
    "protected:\n",
    "    Car car_;\n",
    "};\n",
    "\n",
    "// 具体建造者：卡车\n",
    "class TruckBuilder : public Builder<TruckBuilder> {\n",
    "public:\n",
    "    void buildWheelsImpl() {\n",
    "        this->car_.setWheels(\"Truck Wheels.\");\n",
    "    }\n",
    "\n",
    "    void buildEngineImpl() {\n",
    "        this->car_.setEngine(\"Truck Engine.\");\n",
    "    }\n",
    "};\n",
    "\n",
    "// 具体建造者：摩托车\n",
    "class MotorBuilder : public Builder<MotorBuilder> {\n",
    "public:\n",
    "    void buildWheelsImpl() {\n",
    "        this->car_.setWheels(\"Motor Wheels.\");\n",
    "    }\n",
    "\n",
    "    void buildEngineImpl() {\n",
    "        this->car_.setEngine(\"Motor Engine.\");\n",
    "    }\n",
    "};\n",
    "\n",
    "// 指挥者：接受任意建造者实例（按值接收即可）\n",
    "class Director {\n",
    "public:\n",
    "    template <typename BuilderType>\n",
    "    Car buildCar(BuilderType builder) {\n",
    "        builder.buildWheels();\n",
    "        builder.buildEngine();\n",
    "        return builder.release();\n",
    "    }\n",
    "};\n",
    "\n",
    "int main() {\n",
    "    Director director;\n",
    "\n",
    "    Car truck = director.buildCar(TruckBuilder{});\n",
    "    (void)truck;\n",
    "\n",
    "    Car motor = director.buildCar(MotorBuilder{});\n",
    "    (void)motor;\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Mixin 基础"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "传统继承带来的问题\n",
    "- 每增加一个功能，都要派生新类（如 `Line → SolidLine → ColorSolidLine`），易形成“继承链屎山”。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Mixin 重构思路\n",
    "- 将不同功能拆成独立类，通过模板多继承混入。\n",
    "- `Line` 使用折叠表达式依次调用 mixin 的 `draw()`。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "cpp"
    }
   },
   "outputs": [],
   "source": [
    "// 传统继承方式\n",
    "\n",
    "#include <iostream>\n",
    "\n",
    "// 抽象基类：Line\n",
    "class Line {\n",
    "public:\n",
    "    virtual ~Line() = default;\n",
    "    virtual void draw() = 0;\n",
    "};\n",
    "\n",
    "// 仅具备“实线”特性的线\n",
    "class SolidLine : public Line {\n",
    "public:\n",
    "    void draw() override {\n",
    "        drawSolid();\n",
    "    }\n",
    "\n",
    "protected:\n",
    "    void drawSolid() {\n",
    "        std::cout << \"draw solid line\\n\";\n",
    "    }\n",
    "};\n",
    "\n",
    "// 仅具备“颜色”特性的线\n",
    "class ColoredLine : public Line {\n",
    "public:\n",
    "    void draw() override {\n",
    "        renderColor();\n",
    "    }\n",
    "\n",
    "protected:\n",
    "    void renderColor() {\n",
    "        std::cout << \"render color\\n\";\n",
    "    }\n",
    "};\n",
    "\n",
    "// 同时具备“实线 + 颜色”两种特性的线\n",
    "class ColoredSolidLine : public SolidLine {\n",
    "public:\n",
    "    void draw() override {\n",
    "        drawSolid();   // 调用来自 SolidLine 的能力\n",
    "        renderColor(); // 需要自行实现或间接复用\n",
    "    }\n",
    "\n",
    "private:\n",
    "    void renderColor() {\n",
    "        std::cout << \"render color\\n\";\n",
    "    }\n",
    "};\n",
    "\n",
    "int main() {\n",
    "    ColoredSolidLine line;\n",
    "    line.draw();\n",
    "    // 输出：\n",
    "    // draw solid line\n",
    "    // render color\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "cpp"
    }
   },
   "outputs": [],
   "source": [
    "#include <iostream>\n",
    "\n",
    "// Mixin 容器：通过模板多继承引入所有功能\n",
    "template <typename... Mixins>\n",
    "class Line : public Mixins... {\n",
    "public:\n",
    "    void draw() {\n",
    "        // C++17 折叠表达式：依次调用每个 mixin 的 draw()\n",
    "        (Mixins::draw(), ...);\n",
    "    }\n",
    "};\n",
    "\n",
    "// 功能模块：绘制实线\n",
    "class Solid {\n",
    "public:\n",
    "    void draw() {\n",
    "        std::cout << \"draw solid line\\n\";\n",
    "    }\n",
    "};\n",
    "\n",
    "// 功能模块：渲染颜色\n",
    "class Color {\n",
    "public:\n",
    "    void draw() {\n",
    "        std::cout << \"render color\\n\";\n",
    "    }\n",
    "};\n",
    "\n",
    "int main() {\n",
    "    // 组合多个 mixin，得到拥有两种特性的 Line\n",
    "    Line<Solid, Color> coloredSolidLine;\n",
    "    coloredSolidLine.draw();\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# CRTP + Mixin 的组合使用"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "在 Mixin 中通过 CRTP 调用“最终类”的实现，从而安全地复用派生类逻辑。\n",
    "- 通过 CRTP，`RepeatPrint` mixin 可以访问派生类的 `print()`。\n",
    "- 当前 C++ 标准下无法用可变模板参数将 mixin 列表“插入”到最终类中（类似 `template<template<typename> class... Mixins>` 的写法无法通过编译），使用上仍需手工指定。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "cpp"
    }
   },
   "outputs": [],
   "source": [
    "// 重复打印\n",
    "\n",
    "#include <iostream>\n",
    "\n",
    "// -----------------------------\n",
    "// RepeatPrint Mixin（依赖派生类提供 print()）\n",
    "// -----------------------------\n",
    "template <typename Printable>\n",
    "class RepeatPrint {\n",
    "public:\n",
    "    void repeatPrint(int n) {\n",
    "        for (int i = 0; i < n; ++i) {\n",
    "            static_cast<Printable*>(this)->print();\n",
    "        }\n",
    "    }\n",
    "};\n",
    "\n",
    "// -----------------------------\n",
    "// 终端类 Print：继承 mixin，并提供 print() 实现\n",
    "// -----------------------------\n",
    "class Print : public RepeatPrint<Print> {\n",
    "public:\n",
    "    void print() {\n",
    "        std::cout << \"print function\\n\";\n",
    "    }\n",
    "};\n",
    "\n",
    "// -----------------------------\n",
    "// 再添加一个 mixin，演示多 mixin 叠加\n",
    "// -----------------------------\n",
    "template <typename Printable>\n",
    "class WithPrefix {\n",
    "public:\n",
    "    void printWithPrefix(const std::string& prefix) {\n",
    "        std::cout << prefix;\n",
    "        static_cast<Printable*>(this)->print();\n",
    "    }\n",
    "};\n",
    "\n",
    "class FancyPrint : public RepeatPrint<FancyPrint>, public WithPrefix<FancyPrint> {\n",
    "public:\n",
    "    void print() {\n",
    "        std::cout << \"fancy print\\n\";\n",
    "    }\n",
    "};\n",
    "\n",
    "// -----------------------------\n",
    "// 演示\n",
    "// -----------------------------\n",
    "int main() {\n",
    "    Print p;\n",
    "    p.print();            // 单次\n",
    "    p.repeatPrint(3);     // 调用 mixin 的重复打印\n",
    "\n",
    "    FancyPrint fp;\n",
    "    fp.print();                     // 派生类自己的实现\n",
    "    fp.repeatPrint(2);              // RepeatPrint 中的逻辑\n",
    "    fp.printWithPrefix(\">>> \");     // WithPrefix 中的逻辑\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 实践建议与注意事项"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "1. **选择标准多态 vs 静态多态**\n",
    "   - 需要运行时扩展或动态装载：仍推荐虚函数。\n",
    "   - 性能敏感、类型确定：优先考虑 CRTP。\n",
    "2. **Mixin 设计要点**\n",
    "   - 保持 mixin 单一职责，避免互相依赖。\n",
    "   - 合理使用折叠表达式，防止调用顺序混乱。\n",
    "3. **与现代 C++ 配合**\n",
    "   - C++23 显式对象形参简化 CRTP 写法。\n",
    "   - `std::unique_ptr`、`std::move` 等现代特性可减少资源泄漏风险。\n",
    "4. **可读性与文档**\n",
    "   - CRTP 与 mixin 结合后结构复杂，需充足注释与命名。\n",
    "   - 在团队内建立统一模式示例，降低上手门槛。"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "C++17",
   "language": "C++17",
   "name": "xcpp17"
  },
  "language_info": {
   "name": "C++17"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
